package neuronvisualizer;

import java.awt.Color;

import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;

	/**
	 * Neuron Class
	 * @author John Newsom
	 * 
	 * This is the class that will hold all the data required
	 * to represent a neuron in the network. The network in the
	 * simulator will be a HashMap consisting of instances of 
	 * this class, all linked to their ID for easy referencing.
	 */



public class Neuron{
	private int ID;
	private Type neuronType;
	private int xPos;
	private int yPos;
	private int zPos;
	private Layer layer;
	private Connection[] connections;
	private Object3D model;
	private Object3D glow;
	private boolean sectionShown, typeShown;
	
	public static float maxCharge;
	public static float minCharge;
	
	public boolean deleteFlag,addFlag,visible; 
	//deleteFlag is a marker to tell visual if this neuron model needs to be removed
	//addFlag is a marker to tell visual if this neuron model needs to be added
	//visible is the boolean referencing if this neuron model is currently built or not
	
	private Driver owner;
	/**
	 * Default constructor, sets all properties to empty values
	 */
	public Neuron(){
		sectionShown = true;
		typeShown = true;
		ID = -1;
		neuronType = Type.FS;
		xPos = 0;
		yPos = 0;
		zPos = 0;
		layer = Layer.II;
		connections = null;
		model = null;
		deleteFlag = false;
		visible=false;
	}
	
	/**
	 * Main constructor, includes all necessary values
	 */
	public Neuron(Driver p,int IDnum,Type type,Layer lay,int x,int y,int z,Connection[] c){
		owner = p;
		sectionShown = true;
		typeShown = true;
		ID = IDnum;
		neuronType = type;
		layer = lay;
		xPos = x;
		yPos = y;
		zPos = z;
		connections = c;	
		model = null;
		deleteFlag = false;
		visible = false;
	}
	
	public void buildModel(){
		Object3D temp = null;
		if(neuronType == Type.RS){
			temp = Primitives.getPyramide(15f);
			temp.setShadingMode(Object3D.SHADING_FAKED_FLAT);
			temp.setTexture("green");
		}
		else if(neuronType == Type.FS){
			temp = Primitives.getSphere(6,15f);
			temp.setTexture("dblue");
		}
		else if(neuronType == Type.LTS){
			temp = Primitives.getEllipsoid(6,15f,2);
			temp.setTexture("red");
		}
		else if(neuronType == Type.IB){
			temp = Primitives.getPyramide(15f);
			temp.setShadingMode(Object3D.SHADING_FAKED_FLAT);
			temp.setTexture("blue");
		}
		if(temp!=null){
			temp.setEnvmapped(Object3D.ENVMAP_ENABLED);
			temp.setSelectable(Object3D.MOUSE_SELECTABLE);
			temp.translate(new SimpleVector(xPos,yPos,zPos));
			temp.setSpecularLighting(Object3D.SPECULAR_ENABLED);
			temp.build();
		}
		model = temp;
		createGlow();
		temp = null;
		 
	}
	public void unspark(){
	    if(model!=null && glow!=null){
		glow.setVisibility(false);
	    }
	}
	public void spark(){
	    if(model!=null && glow!=null){
			glow.setVisibility(true);
	    }
	}
	public void createGlow(){
	    if(model!=null){
	    	glow = Primitives.getPlane(5, 15f);
                glow.setCulling(false);

                glow.setBillboarding(Object3D.BILLBOARDING_ENABLED);
    	    	glow.setTexture("glow");
    	    	glow.translate(model.getTransformedCenter());
    	    	glow.setTransparency(0);
    	    	glow.setTransparencyMode(Object3D.TRANSPARENCY_MODE_ADD);
    	    	
    	    	glow.setLighting( Object3D.LIGHTING_NO_LIGHTS);
    	    	glow.setAdditionalColor( new Color( 255,255,255) );
    	    	
    	    	glow.build();
    	    	glow.setVisibility(false);
	    }
	    else{
	    	System.out.println(""+(model==null));
	    }
	}
	
	public SimpleVector getLocation(){
		return new SimpleVector(xPos,yPos,zPos);
	}
	
	/**
	 * Used to add a new connection to a neuron at run-time.
	 */
	public void setConnections(Connection[] c){
		connections = c;
	}
	
	/**
	 * Returns the size of the connection list
	 */
	public int numberOfConnections(){
		return connections.length;
	}
	
	/**
	 * Returns the list of the connections
	 */
	public Connection[] getConnections(){
		return connections;
	}
	
	
	/**
	 * Change or retrieve the 3d coordinates of the neuron.
	 */
	public int getX(){
		return xPos;
	}
	public void setX(int x){
		xPos = x;
	}
	
	public int getY(){
		return yPos;
	}
	public void setY(int y){
		yPos = y;
	}
	
	public int getZ(){
		return zPos;
	}
	public void setZ(int z){
		zPos = z;
	}
	
	public void hideConnections(){
		if (connections != null)
			for(Connection c:connections){
				c.deleteFlag = true;
			}
	}
	
	public void showConnections(){
		if (connections != null)
			for(Connection c:connections){
				c.addFlag = true;
			}
	}
	

	/**
	 * Change or retrieve the Neuron type
	 */
	public Type getType(){
		return neuronType;
	}
	public void setType(Type t){
		neuronType = t;
	}

	
	/**
	 * Change or retrieve the layer of the Neuron
	 */
	public Layer getLayer(){
		return layer;
	}
	public void setLayer(Layer l){
		layer = l;
	}
	
	/**
	 * Change or retrieve ID of the Neuron
	 */
	public int getID(){
		return ID;
	}
	public void setID(int id){
		ID = id;
	}
	
	/**
	 * Change or retrieve the neuron's model
	 */
	public Object3D getModel(){
		return model;
	}
	
	public Object3D getGlow(){
	    	return glow;
	}
	
	public void typeShow(){
		if(sectionShown){
			buildModel();
			addFlag = true;
		}
		typeShown = true;
	}
	public void typeHide(){
			deleteFlag = true;
			typeShown = false;
	}
	public void hide(){
			deleteFlag = true;
			sectionShown = false;
		
	}
	public void show(){
		if(typeShown){
			buildModel();
			addFlag = true;
		}
		sectionShown = true;
	}
	
	public void destroyModel(){
		//visual has removed model, safe to clear flags and destroy the model
		model = null;
		glow = null;
		deleteFlag = false;
		visible = false;
	}
	public void modelBuilt(){
		//visual has added the model, safe to clear flags
		addFlag = false;
		visible = true;
	}
	
	public float getScale(){
		return model.getScale();
	}
	public void setScale(float s){
		model.scale(s);
	}

	
}//END CLASS NEURON